﻿using System;
using System.Collections.Generic;
using System.Xml;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace GameEngine
{
    public class Level
    {
        //------------------- Vars

        ContentManager Content;

        List<Layer> layers = new List<Layer>();

        int level_width, level_height, tile_width, tile_height;

        Vector2 screen_size = Vector2.Zero;

        Player player;

        //------------------- Constructs

        public Level(ContentManager Content, string filename, Vector2 screen_size, int tile_width, int tile_height)
        {
            this.Content = Content;
            this.screen_size = screen_size;
            this.tile_width = tile_width;
            this.tile_height = tile_height;

            ReadLevel(filename);

            player = new Player(Content.Load<Texture2D>("Sprites/characters"), 16, 16);
        }

        //------------------- Functions

        // This gets the XML file containing the level data and reads it
        public void ReadLevel(string filename)
        {
            FileStream file_stream = new FileStream("Content/Levels/" + filename + ".xml", FileMode.Open, FileAccess.Read);
            XmlReader reader = XmlReader.Create(file_stream);

            string element = null, text = null;
            Sprite sprite = new Sprite(tile_width, tile_height);

            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.Element)
                {
                    element = reader.Name;

                    if (reader.Name == "level")
                    {
                        this.level_width = Convert.ToInt32(reader.GetAttribute(0));
                        this.level_height = Convert.ToInt32(reader.GetAttribute(1));
                    }
                }
                else if (reader.NodeType == XmlNodeType.Text)
                {
                    text = reader.Value;

                    switch (element)
                    {
                        case "sprite":
                            sprite = new Sprite(Content.Load<Texture2D>("Sprites/" + reader.Value), tile_width, tile_height);
                            break;

                        case "layers":
                            ReadLayers(reader.Value, sprite);
                            break;
                    }
                }
            }
        }

        // This takes the layers file and reads through it setting up the layers in the level
        public void ReadLayers(string filename, Sprite sprite)
        {
            bool reading_layer = false;
            float alpha = 1.0f;
            List<List<int>> temp_layer = new List<List<int>>();

            using (StreamReader reader = new StreamReader("Content\\Levels\\" + filename))
            {
                while (!reader.EndOfStream)
                {
                    string line = reader.ReadLine().Trim();

                    if (string.IsNullOrEmpty(line))
                        continue;

                    switch (line)
                    {
                        case "[LAYER]":
                            reading_layer = true;

                            temp_layer = new List<List<int>>();
                            line = reader.ReadLine().Trim();
                            break;

                        case "[/LAYER]":
                            reading_layer = false;

                            CreateLayer(temp_layer, sprite, alpha);
                            break;

                        case "[ALPHA]":
                            reading_layer = false;
                            line = reader.ReadLine().Trim();

                            if (!string.IsNullOrEmpty(line))
                                alpha = MathHelper.Clamp((float)Convert.ToDouble(line), 0, 1);
                            break;
                    }

                    if (reading_layer)
                    {
                        List<int> row = new List<int>();

                        string[] cells = line.Split(' ');

                        foreach (string cell in cells)
                        {
                            if (!string.IsNullOrEmpty(cell))
                                row.Add(int.Parse(cell));
                        }

                        temp_layer.Add(row);
                    }
                }
            }
        }

        // This creates a layer to be drawn
        public void CreateLayer(List<List<int>> temp_layer, Sprite sprite, float alpha)
        {

            Layer layer = new Layer(temp_layer[0].Count, temp_layer.Count, sprite, tile_width, tile_height, alpha);

            for (int y = 0; y < temp_layer.Count; y++)
            {
                for (int x = 0; x < temp_layer[0].Count; x++)
                {
                    layer.SetCellIndex(x, y, temp_layer[y][x]);
                }
            }

            layers.Add(layer);
        }

        //------------------- Base functions

        public void Update(GameTime gameTime)
        {
            player.Update(gameTime);
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            foreach (Layer layer in layers)
            {
                layer.Draw(spriteBatch);
            }

            player.Draw(spriteBatch);
        }
    }
}
